package com.cd.javacxy.module.web.service.impl;

import cn.hutool.core.util.StrUtil;
import com.cd.javacxy.common.model.entity.CxyAttachment;
import com.cd.javacxy.common.model.entity.CxyTopic;
import com.cd.javacxy.common.model.entity.CxyTopicVote;
import com.cd.javacxy.common.model.enums.*;
import com.cd.javacxy.common.model.query.MessageParams;
import com.cd.javacxy.common.model.query.TopicQuery;
import com.cd.javacxy.common.model.query.UpdateQuery4ArticleCount;
import com.cd.javacxy.common.utils.CxyUtils;
import com.cd.javacxy.common.utils.ImageUtils;
import com.cd.javacxy.common.utils.Page;
import com.cd.javacxy.common.utils.PageResult;
import com.cd.javacxy.exception.BussinessException;
import com.cd.javacxy.module.web.dao.CxyTopicDao;
import com.cd.javacxy.module.web.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * CxyTopic的服务接口的实现类
 *
 * @author yanghy
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CxyTopicServiceImpl implements CxyTopicService {

    private final CxyTopicDao cxyTopicDao;
    private final CxyAttachmentService attachmentService;
    private final FormateAtService formateAtService;
    private final CxyUserService userService;
    private final CxyMessageService messageService;
    private final CxyTopicVoteService topicVoteService;
    private final CxyCategoryService cxyCategoryService;

    @Override
    public CxyTopic getTopic(Integer topicId) {
        if (topicId == null) {
            return null;
        }
        TopicQuery topicQuery = new TopicQuery();
        topicQuery.setShowContent(Boolean.TRUE);
        topicQuery.setTopicId(topicId);
        List<CxyTopic> list = this.cxyTopicDao.selectList(topicQuery);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public PageResult<CxyTopic> findTopicByPage(TopicQuery topicQuery) {
        int count = this.cxyTopicDao.selectCount(topicQuery);
        int pageSize = PageSize.PAGE_SIZE20.getSize();
        int pageNum = 1;
        if (topicQuery.getPageNum() != 1) {
            pageNum = topicQuery.getPageNum();
        }
        Page page = new Page(pageNum, count, pageSize);
        topicQuery.setPage(page);
        topicQuery.setOrderBy(OrderByEnum.LAST_COMMENT_TIME_DESC_CREATE_TIME_DESC);
        List<CxyTopic> list = this.cxyTopicDao.selectList(topicQuery);
        return new PageResult<>(page, list);
    }

    @Override
    public List<CxyTopic> findActiveUsers() {
        return this.cxyTopicDao.selectActiveUser4Topic();
    }

    @Override
    public int findCount(TopicQuery topicQuery) {
        return this.cxyTopicDao.selectCount(topicQuery);
    }

    @Override
    public CxyTopic showTopic(Integer topicId) throws BussinessException {
        CxyTopic topic = this.getTopic(topicId);
        if (topic == null) {
            throw new BussinessException("帖子不存在或已删除");
        }
        topic.setAttachment(this.attachmentService.getAttachmentByTopicIdAndFileType(topic.getTopicId(), FileTopicType.TOPIC));
        UpdateQuery4ArticleCount updateQuery4ArticleCount = new UpdateQuery4ArticleCount();
        updateQuery4ArticleCount.setAddReadCount(Boolean.TRUE);
        updateQuery4ArticleCount.setArticleId(topicId);
        this.cxyTopicDao.updateInfoCount(updateQuery4ArticleCount);
        return topic;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addTopic(CxyTopic topic, CxyTopicVote topicVote, String[] voteTitle, CxyAttachment attachment) throws BussinessException {
        if (topic.getTopicType() == null
                || topic.getTitle() == null
                || topic.getTitle().length() > TextLengthEnum.TEXT_200_LENGTH
                .getLength()
                || topic.getCategoryId() == null
                || StrUtil.isEmpty(topic.getContent())
                || topic.getContent().length() > TextLengthEnum.LONGTEXT
                .getLength()) {
            throw new BussinessException("参数错误");
        }
        String title = topic.getTitle();
        topic.setTitle(HtmlUtils.htmlEscape(title));
        String content = topic.getContent();
        String summary = CxyUtils.cleanHtmlTag(HtmlUtils.htmlUnescape(content));
        if (summary.length() > TextLengthEnum.TEXT_200_LENGTH.getLength()) {
            summary = summary.substring(0,
                    (int) TextLengthEnum.TEXT_200_LENGTH.getLength())
                    + "......";
        }
        Set<Integer> userIds = new HashSet<>();
        String formatContent = formateAtService.generateRefererLinks(content, userIds);
        // TODO 给用户发消息
        topic.setSummary(summary);
        topic.setContent(formatContent);
        String topicImage = ImageUtils.getImages(content);
        topic.setTopicImage(topicImage);
        String topicImageSmall = ImageUtils.createThumbnail(topicImage, true);
        topic.setTopicImageThum(topicImageSmall);
        topic.setCreateTime(new Date());
        topic.setLastCommentTime(LocalDateTime.now());
        this.cxyTopicDao.insert(topic);
        this.userService.changeMark(topic.getUserId(),
                MarkEnum.MARK_TOPIC.getMark());
        // 判断是否是投票贴
        if (topic.getTopicType() == TopicType.VOTE) {
            topicVote.setTopicId(topic.getTopicId());
            this.topicVoteService.addVote(topicVote, voteTitle);
        }
        if (StrUtil.isNotBlank(attachment.getFileName()) && StrUtil.isNotBlank(attachment.getFileUrl())) {
            attachment.setTopicId(topic.getTopicId());
            attachment.setTopicType(FileTopicType.TOPIC);
            this.attachmentService.addAttachment(attachment);
        }

        MessageParams messageParams = new MessageParams();
        messageParams.setArticleId(topic.getTopicId());
        messageParams.setArticleType(ArticleType.TOPIC);
        messageParams.setArticleUserId(topic.getUserId());
        messageParams.setMessageType(MessageType.AT_ARTICLE_MESSAGE);
        messageParams.setSendUserName(topic.getUserName());
        messageParams.setSendUserId(topic.getUserId());
        messageParams.setReceiveUserIds(userIds);
        messageService.createMessage(messageParams);
    }
}